package com.css.fxfzfxqh.base.dict.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.css.fxfzfxqh.base.cache.CacheService;
import com.css.fxfzfxqh.base.dict.repository.DictItemRepository;
import com.css.fxfzfxqh.base.dict.repository.entity.DictItemEntity;
import com.css.fxfzfxqh.base.dict.service.DictItemService;
import com.css.fxfzfxqh.base.dict.viewobjects.DictEntityVo;
import com.css.fxfzfxqh.base.dict.viewobjects.DictItemQueryParams;
import com.css.fxfzfxqh.base.dict.viewobjects.DictItemVO;
import com.css.fxfzfxqh.base.response.RestResponse;
import com.css.fxfzfxqh.constants.FxfzConstants;
import com.css.fxfzfxqh.constants.YNEnum;
import com.css.fxfzfxqh.util.*;
import com.css.util.Json;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.css.fxfzfxqh.constants.FxfzConstants.CACHE_SYS_KEY;

@Service
@Slf4j
public class DictItemImpl implements DictItemService {
    @Autowired
    DictItemRepository dictItemRepository;

    @Resource
    JdbcTemplate jdbcTemplate;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    CacheService cacheService;

    private static final String CACHE_DICT_ITEM_ID_KEY = "dictItemId:";
    private static final String CACHE_DICT_CODE_LIST_KEY = "dictCodeList:";

    @Override
    public JSONObject queryDictItems(DictItemQueryParams queryParams, int curPage, int pageSize) {
        Page<DictItemEntity> itemEntities = dictItemRepository.queryDictItems(queryParams, curPage, pageSize);
        JSONObject jsonObject = PlatformPageUtils.formatPageData(itemEntities);
        return jsonObject;
    }

    @Override
    public DictItemEntity saveDictItem(DictItemEntity itemEntity) {
        String uuid = UUIDGenerator.getUUID();
        itemEntity.setDictItemId(uuid);
        itemEntity.setIsValid(YNEnum.Y.toString());
        itemEntity.setCreateUser(PlatformSessionUtils.getUserId());
        itemEntity.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
        dictItemRepository.saveDictItem(itemEntity);
        String dictCode = dictItemRepository.findDictCodeByDictItemId(itemEntity.getDictItemId());
        cacheService.delete(CACHE_SYS_KEY + CACHE_DICT_CODE_LIST_KEY + dictCode);
        return itemEntity;
    }

    @Override
    public DictItemEntity updateDictItem(DictItemEntity itemEntity) {
        itemEntity.setUpdateUser(PlatformSessionUtils.getUserId());
        itemEntity.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
        dictItemRepository.saveDictItem(itemEntity);
        String dictCode = dictItemRepository.findDictCodeByDictItemId(itemEntity.getDictItemId());
        cacheService.delete(CACHE_SYS_KEY + CACHE_DICT_ITEM_ID_KEY + itemEntity.getDictItemId());
        cacheService.delete(CACHE_SYS_KEY + CACHE_DICT_CODE_LIST_KEY + dictCode);
        return itemEntity;
    }

    @Override
    public DictItemEntity getDictItem(String id) {
        DictItemEntity itemEntity = null;
        itemEntity = (DictItemEntity) cacheService.get(CACHE_SYS_KEY + CACHE_DICT_ITEM_ID_KEY + id);
        if (PlatformObjectUtils.isEmpty(itemEntity)) {
            itemEntity = dictItemRepository.findById(id);
            cacheService.set(CACHE_SYS_KEY + CACHE_DICT_ITEM_ID_KEY + id, itemEntity);
        }
        return itemEntity;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteDictItems(List<String> ids) {
        deleteDictCache(ids);
        dictItemRepository.delete(ids);
    }

    @Override
    public boolean validateDictItemCode(String dictId, String dictItemId, String dictItemCode) {
        boolean isValid = false;
        DictItemEntity dte = dictItemRepository.findOneByDictItemCodeAndDictId(dictItemCode, dictId);
        if (PlatformObjectUtils.isEmpty(dte)) {
            isValid = false;
        } else if (dte.getDictItemId().equals(dictItemId)) {
            isValid = true;
        }
        return isValid;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateDictItems(List<String> ids, String type) {
        List<DictItemEntity> dictEntitys = dictItemRepository.findAllById(ids);
        deleteDictCache(ids);
        for (DictItemEntity dictEntity : dictEntitys) {
            if ("1".equals(type)) {
                dictEntity.setIsValid(YNEnum.Y.toString());
            } else {
                dictEntity.setIsValid(YNEnum.N.toString());
            }
            dictEntity.setUpdateUser(PlatformSessionUtils.getUserId());
            dictEntity.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
            dictItemRepository.saveDictItem(dictEntity);
        }
    }

    private void deleteDictCache(List<String> ids) {
        List<String> dictCacheKeys = new ArrayList<String>();
        List<DictItemEntity> dictItems = dictItemRepository.findAllById(ids);
        List<String> dictCodes = dictItemRepository.findDictCodeByDictItemIds(ids);
        if (PlatformObjectUtils.isNotEmpty(dictItems)) {
            for (DictItemEntity dictItem : dictItems) {
                dictCacheKeys.add(CACHE_SYS_KEY + CACHE_DICT_ITEM_ID_KEY + dictItem.getDictItemId());
            }
        }
        if (PlatformObjectUtils.isNotEmpty(dictCodes)) {
            for (String dictCode : dictCodes) {
                dictCacheKeys.add(CACHE_SYS_KEY + CACHE_DICT_CODE_LIST_KEY + dictCode);
            }
        }
        cacheService.delete(dictCacheKeys);
    }

    @Override
    public List<DictEntityVo> getDictItemByDictCode(String dictCode) {
        StringBuilder sql = new StringBuilder("select dict.dict_id,dict.dict_name,dict.dict_code,item.dict_item_code,item.dict_item_name from sys_dict dict,sys_dict_item item " +
                " where dict.dict_id = item.dict_id and dict.is_valid='1' and item.is_valid='1'");
        if (StringUtils.isNotBlank(dictCode)) {
            sql.append(" and dict.dict_code ='").append(dictCode).append("'");
        }
        List<DictEntityVo> vos = jdbcTemplate.query(sql.toString(), new BeanPropertyRowMapper<>(DictEntityVo.class));
        Map<String, List<DictEntityVo>> map = buildDictMap(vos);
        //分类放到redis
        for (Map.Entry<String, List<DictEntityVo>> m : map.entrySet()) {
            redisTemplate.opsForValue().set(FxfzConstants.CACHE_SYS_KEY + m.getKey(), JSONObject.toJSONString(m.getValue()));
        }
        return vos;
    }

    @Override
    public DictItemEntity getDictItemByDictCodeAndItemCode(String dictCode, String dictItemCode) {
        String sql = "select dict_item.* from sys_dict_item dict_item left join sys_dict dict on dict_item.dict_id = dict.dict_id where dict.dict_code = '" + dictCode + "' and dict_item.dict_item_code = '" + dictItemCode + "' limit 1 offset 0";
        return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(DictItemEntity.class));
    }

    @Override
    public List<String> getDictItemNameByDictId(String dictId) {
        String sql = "select dict_item_name from sys_dict_item where is_valid='1' and  dict_id='"+dictId+"'";
        return jdbcTemplate.queryForList(sql, String.class);
    }

    @Override
    public List<DictItemEntity> getDictItemList(String dictId) {
        String sql = "select * from sys_dict_item where is_valid='1' ";
        if(StringUtils.isNotBlank(dictId)){
            sql+=" and  dict_id='"+dictId+"'";
        }
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(DictItemEntity.class));
    }

    Map<Object, Object> dictItemMap=null;
    @Override
    public Map<Object, Object> getDictItemMap() {
        String sql = "select dict_id,dict_item_code,dict_item_name,dict_id from sys_dict_item where is_valid='1'";
        List<DictEntityVo> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(DictEntityVo.class));
        //分类放到redis
        if (dictItemMap==null) {
            dictItemMap=new HashMap<>();
            for (DictEntityVo vo : query){
                dictItemMap.put(vo.getDictId()+"-"+vo.getDictItemCode(), vo.getDictItemName());
            }
            redisTemplate.opsForHash().putAll(FxfzConstants.CACHE_SYS_KEY + "dictItemMap",dictItemMap);
            redisTemplate.expire(FxfzConstants.CACHE_SYS_KEY + "dictItemMap", 1, TimeUnit.HOURS);
        }
        if(PlatformObjectUtils.isNotEmpty(query) && query.size()>0){
            dictItemMap = query.stream().filter(dictEntityVo -> {
                return ("100002".equals(dictEntityVo.getDictId()) || "100003".equals(dictEntityVo.getDictId()) || "100004".equals(dictEntityVo.getDictId()) || "100005".equals(dictEntityVo.getDictId()));
            }).collect(Collectors.toMap(DictEntityVo::getDictItemCode, DictEntityVo::getDictItemName));
            redisTemplate.opsForHash().putAll("FXQH:"+FxfzConstants.CACHE_SYS_KEY + "dictItemMapForEvaluate",dictItemMap);
            // 设置过期时间为 24 小时
            redisTemplate.expire("FXQH:"+FxfzConstants.CACHE_SYS_KEY + "dictItemMapForEvaluate", 24, TimeUnit.HOURS);
        }
        return dictItemMap;
    }

    /**
     * @param dictEntityVoList
     * @return java.util.List<com.css.fxfzfxqh.base.dict.viewobjects.DictEntityVo>
     * @desc 字典数据构建map结构
     */
    private Map<String, List<DictEntityVo>> buildDictMap(List<DictEntityVo> dictEntityVoList) {
        Map<String, List<DictEntityVo>> map = new HashMap<String, List<DictEntityVo>>(dictEntityVoList.size());
        List<DictEntityVo> vos = new ArrayList<>();
        for (DictEntityVo dictEntityVo : dictEntityVoList) {
            if (!map.containsKey(dictEntityVo.getDictCode())) {
                //如果map没有添加过对应的key则添加
                vos.add(dictEntityVo);
                map.put(dictEntityVo.getDictCode(), vos);
                vos = new ArrayList<>();
                continue;
            }
            //如果map有添加过对应的key则取出value值加入新的值再放入map中
            List<DictEntityVo> dictEntityVos = map.get(dictEntityVo.getDictCode());
            dictEntityVos.add(dictEntityVo);
            map.put(dictEntityVo.getDictCode(), dictEntityVos);
        }
        return map;
    }

    @Override
    public RestResponse getDictItemByDictId(String dictId) {
        List<DictItemVO> list = new ArrayList<>();
        List<DictItemEntity> entities = dictItemRepository.getDictItemByDictId(dictId);
        if(PlatformObjectUtils.isNotEmpty(entities) && entities.size()>0){
            for (DictItemEntity entity:entities){
                DictItemVO dictItemVO = new DictItemVO();
                dictItemVO.setDictItemId(entity.getDictItemId());
                dictItemVO.setDictItemName(entity.getDictItemName());
                list.add(dictItemVO);
            }
        }
        return RestResponse.succeed(list);
    }

}
